package fons.navigator.views.island.maps;

import fons.model.ontology.ValueSpace;
import fons.navigator.views.island.Island;
import fons.navigator.views.island.VisualIsland;

public class Neuron {
	private final VisualIsland visualIsland;
	private final int x, y;
	private final int size;
	private final double weights[];
	
	private double scale = 0;
		
	public void setScale (double scale) {
		this.scale = scale;
	}
	
	public double getScale() {
		return this.scale;
	}
	
	public int getX() {
		return x;
	}
	
	public int getY() {
		return y;
	}
	
	public Neuron(int x, int y, int size, int dimensionality, VisualIsland visualIsland) {
		this.visualIsland = visualIsland;
		this.x = x;
		this.y = y;
		this.size = size;
		this.weights = new double[dimensionality];
		
		for (int i = 0; i < dimensionality; ++i) {
			weights[i] = Math.random();
		}
	}
	
	public double distance(Island island) {
		double d = 0;
		int i = 0;
		for (ValueSpace vsp: visualIsland.getValueSpaces()) {
			final double value = island.getValueOf(vsp);
			d += (value - weights[i]) * (value - weights[i]);
			i++;
		}
		d = Math.sqrt(d);
		return d;
	}
	
	public double weightDistance (Neuron other) {
		double d = 0;
		for (int i = 0; i < weights.length; ++i) {
			d += (weights[i]-other.weights[i])*(weights[i]-other.weights[i]);
		}
		return Math.sqrt(d);
	}
	
	public double distance (Neuron other) {
		
		int dx = x - other.x;
		if (dx > size/2) dx = size - dx;
		else if (dx < -size/2) dx = size + dx;
		
		int dy = y - other.y;
		if (dy > size/2) dy = size - dy;
		else if (dy < -size/2) dy = size + dy;
		
		return Math.sqrt(dx*dx + dy*dy);
	}

	public void learn(Island island, double factor) {
		int i = 0;
		for (ValueSpace vsp: visualIsland.getValueSpaces()) {
			final double value = island.getValueOf(vsp);
			weights[i] = weights[i] + factor * (value - weights[i]);			
			i++;
		}
	}

	public float getWeight(int i) {
		return (float) weights[i];
	}
}
